package com.modules.upms.controller;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.exceptions.ClientException;
import com.common.cache.TimedLoaclCache;
import com.common.constant.SecurityConstants;
import com.common.util.Assert;
import com.common.util.R;
import com.common.util.SmsUtil;
import com.common.util.template.MobileMsgTemplate;
import com.google.code.kaptcha.Producer;
import com.modules.upms.entity.resp.CodeResp;
import com.modules.upms.service.SysUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;

/**
 * 验证码提供
 */
@Slf4j
@Api(tags = {"验证码提供相关接口"})
@RestController
@RequestMapping(value = "/vcc")
public class VccController {

    @Autowired
    private Producer producer;
    @Autowired
    private SysUserService sysUserService;
    /**
     * 验证码超时时间，秒
     */
    @Value("${sms.expiration}")
    private Long expiration;
    @Value("${sms.templateCode}")
    private String templateCode;
    @Value("${sms.signName}")
    private String signName;
    @Value("${sms.accessKeyId}")
    private String accessKeyId;
    @Value("${sms.accessKeySecret}")
    private String accessKeySecret;

    /**
     * 创建验证码
     *
     * @param request request
     * @throws Exception
     */
    @GetMapping(value = "/{randomStr}")
    public void createCode(@PathVariable String randomStr, HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        Assert.isBlank(randomStr, "机器码不能为空");
        response.setHeader("Cache-Control", "no-store, no-cache");
        response.setContentType("image/jpeg");
        //生成文字验证码
        String text = producer.createText();
        //生成图片验证码
        BufferedImage image = producer.createImage(text);
        sysUserService.saveImageCode(randomStr, text);
        ServletOutputStream out = response.getOutputStream();
        ImageIO.write(image, "JPEG", out);
        IOUtils.closeQuietly(out);
    }

    /**
     * 发送手机验证码
     *
     * @param mobile 手机号
     * @return R
     */
    @ApiOperation(value = "发送手机验证码")
    @GetMapping(value = "/sendSms/{mobile}")
    public R<CodeResp> createCode(@PathVariable String mobile) {

        Assert.isBlank(mobile, "手机号不能为空");

        CodeResp codeResp = new CodeResp();

        String codeCacheKey = SecurityConstants.DEFAULT_CODE_KEY + mobile;

//        String tempCode = TimedLoaclCache.CODE_CACHE.get(codeCacheKey);
//        if (tempCode != null) {
//            log.error("用户:{}验证码未失效{}", mobile, tempCode);
//            return R.error( "验证码未失效，请失效后再次申请");
//        }

        String code = RandomUtil.randomNumbers(6);

        JSONObject contextJson = new JSONObject();
        contextJson.put("code", code);

        MobileMsgTemplate mobileMsgTemplate = new MobileMsgTemplate(mobile, contextJson.toJSONString(),
                signName, templateCode, accessKeyId, accessKeySecret);

        try {
            SmsUtil.sendAliyunSms(mobileMsgTemplate);
        } catch (ClientException e) {
            log.info("短信发送失败 -> 手机号:{} -> 验证码：{}", mobile, code);
            return R.error();
        }

        TimedLoaclCache.CODE_CACHE.put(codeCacheKey, code, expiration * 1000);

        codeResp.setCode(code);
        codeResp.setExpiration(expiration);

        log.info("短信发送 -> 手机号:{} -> 验证码：{}", mobile, code);
        return R.success(codeResp);
    }

    /**
     * 验证手机验证码
     *
     * @param mobile 手机号
     * @return R
     */
    @ApiOperation(value = "验证手机验证码")
    @GetMapping(value = "/smsValidate/{mobile}/{code}")
    public R smsValidate(@PathVariable String mobile, @PathVariable String code) {

        Assert.isBlank(mobile, "手机号不能为空");

        String codeCacheKey = SecurityConstants.DEFAULT_CODE_KEY + mobile;

        String tempCode = TimedLoaclCache.CODE_CACHE.get(codeCacheKey);
        if(StrUtil.isBlank(tempCode)) {
            return R.error( "验证码已失效");
        }

        if (!StrUtil.equals(tempCode, code)) {
            log.warn("tempCode=",tempCode, ";code=", code);
            return R.error( "验证码不一致");
        }

        return R.success();
    }
}
